﻿// openmp_pi.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include <cassert>
#include <chrono>
#include <omp.h>

int main()
{
    const int N = 10000000;    // 区间个数
    const double dx = 1.0 / (double)N;    // 区间长度

    omp_set_num_threads(8);    // 设置线程个数

    auto t0 = std::chrono::high_resolution_clock::now();    // 获取当前时刻
    double pi = 0;

#pragma omp parallel
    {
        // 获取线程总数 nt
        int nt = 0;
        nt = omp_get_num_threads();

        // 获取当前线程编号 it
        int it = 0;
        it = omp_get_thread_num();    // ip从0开始

        assert(N % nt == 0);
        // 当前线程上的区间个数
        int n = N / nt;

        // 计算当前线程上的部分
        double x = (double)it / (double)nt;
        double pi_i = 0;
        for (int i = 0; i < n; i++) {
            pi_i += 4 / (1 + x * x) * dx;
            x += dx;
        }

        // 对所有线程上的pi_i 求和
#pragma omp atomic
        pi += pi_i;
    }
   
    // 结束时刻
    auto t1 = std::chrono::high_resolution_clock::now();
    auto t = std::chrono::duration<double>(t1 - t0).count();

    // 在根进程root上输出结果
    std::cout << "pi = " << std::scientific << pi
            << " , t = " << std::fixed << t << "\n"; 
}

